package game.efficientCollisionPrediction;

import game.SpaceObject;
import game.World;

import java.util.*;

/**
 * A class of CollisionPredictors that lists all the potential collisions of its source.
 * @invar	hasProperFutureCollisions()
 * @author JeroenGillis && ThomasProvoost
 */
public class CollisionPredictor {
	
	private final TreeSet<FutureCollision> order;
	private final HashMap<SpaceObject, HashMap<SpaceObject,FutureCollision>> components = new HashMap<SpaceObject,HashMap<SpaceObject,FutureCollision>>();
	private final World world;
	
	public CollisionPredictor(World world) {
		
		this.order = new TreeSet<FutureCollision>();
		this.world = world;
	}
	
	// belangrijkste methodes
	
	public void makeNewFutureCollisions(SpaceObject object) {
		// TODO
		// nieuwe hashmap voor object, voor elk ander object in world een nieuwe FutureCollision
		// nieuwe FC's ook in treeset toevoegen
		
		HashMap<SpaceObject,FutureCollision> newMap = new HashMap<SpaceObject,FutureCollision>();
		for(SpaceObject inWorld : world.getAllSpaceObjects()) {
			if(inWorld != object) {
				FutureEntityCollision newFC = new FutureEntityCollision(object, inWorld);
				components.get(inWorld).put(object, newFC);
				newMap.put(inWorld, newFC);
				order.add(newFC);
			}
		}
		FutureBoundaryCollision boundaryCollision = new FutureBoundaryCollision(object);
		order.add(boundaryCollision);
		newMap.put(object, boundaryCollision);
		components.put(object, newMap);
	}
	
	public void removeFutureCollisions(SpaceObject object) {
		// TODO
		// hashmap over object verwijderen, voor elk ander object in world de FC over object verwijderen
		// ook in TreeSet FC's verwijderen
		
		HashMap<SpaceObject, FutureCollision> mapToRemove = components.get(object);
		order.remove(mapToRemove.get(object));
		for(SpaceObject inWorld : world.getAllSpaceObjects()) {
			FutureCollision toRemove = mapToRemove.get(inWorld);
			order.remove(toRemove);
			components.get(inWorld).remove(object);
		}
		components.remove(object);
	}
	
	public void updateFutureCollisions(Collection<SpaceObject> objects) {
		// TODO
		// alle FC's die betrekking hebben tot de spaceobjecten uit objects removen uit Treeset, updaten en er terug insteken.
		
		for(SpaceObject object : objects) {
			
			if(components.get(object) != null) {
				for(FutureCollision fc : components.get(object).values()) 
				{
					order.remove(fc);
					fc.update();
					order.add(fc);
				}
		}
	}
	}
	
	public FutureCollision getNextCollision() {
		return order.first();
	}

	public Object getWorld() {
		return this.world;
	}

	public Object get(SpaceObject object1, SpaceObject object2) {
		return components.get(object1).get(object2);
	}
}
